using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace XmlObjects.XmlWriter
{
	public class XmlWriterFactory
	{
		static Dictionary<Type, Type> basicTypes = new Dictionary<Type, Type>();

		static XmlWriterFactory()
		{
			basicTypes.Add(typeof(string), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(decimal), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(float), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(long), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(int), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(double), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(bool), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(DateTime), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(DirectoryInfo), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(FileInfo), typeof(BasicXmlWriter));
			basicTypes.Add(typeof(List<>), typeof(ListXmlWriter<>));
		}

		public static IXmlWriter GetWriter(PropertyInfo propertyInfo)
		{
			ElementToPropertyMap map = new ElementToPropertyMap(propertyInfo);
			return GetWriter(propertyInfo.PropertyType, map);
		}

		public static IXmlWriter GetWriter(Type type)
		{
			ElementToPropertyMap map = new ElementToPropertyMap(type);
			return GetWriter(type, map);
		}

		public static IXmlWriter GetWriter(Type typeToWrite, ElementToPropertyMap map)
		{
			Type writerType = null;
			if (basicTypes.ContainsKey(typeToWrite))
				writerType = basicTypes[typeToWrite];
			else
			{
				if (typeToWrite.IsGenericType)
				{
					Type genericTypeDef = typeToWrite.GetGenericTypeDefinition();
					if (basicTypes.ContainsKey(genericTypeDef))
					{
						writerType = basicTypes[genericTypeDef].MakeGenericType(typeToWrite.GetGenericArguments());
					}
				}
				if (writerType == null)
					writerType = typeof (Dehydrator<>).MakeGenericType(typeToWrite);
				basicTypes.Add(typeToWrite, writerType);
			}

			return (IXmlWriter) Activator.CreateInstance(writerType, map);
		}

	}
}